{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "a663157f",
   "metadata": {},
   "source": [
    "# spice.py 使用示例：一个差分放大器的计算\n",
    "\n",
    "本例中计算以下差分放大器的传输特性[(来源)](https://sites.bu.edu/engcourses/files/2016/08/mosfet-differential-amplifier.pdf)。\n",
    "\n",
    "![](circuit.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8da73b1e",
   "metadata": {},
   "outputs": [],
   "source": [
    "from spice import V,R,MOSFET,solve,clear,Vertex\n",
    "from numpy import linspace\n",
    "\n",
    "NMOS = lambda G,D,S,ratio,V_DS=2: MOSFET(G=G,D=D,S=S,mode=\"depletion\",\n",
    "        V_TN=1,channel=\"N\",K=ratio*1e-5,l=1e-2,V_DS=V_DS)\n",
    "PMOS = lambda G,D,S,ratio,V_DS=2: MOSFET(G=G,D=D,S=S,mode=\"depletion\",\n",
    "        V_TN=1,channel=\"P\",K=ratio*5e-6,l=1e-2,V_DS=V_DS)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "06d56a9c",
   "metadata": {},
   "outputs": [
    {
     "ename": "LinAlgError",
     "evalue": "Singular matrix",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mLinAlgError\u001b[0m                               Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_22315/4105025696.py\u001b[0m in \u001b[0;36m<cell line: 22>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     20\u001b[0m \u001b[0mPMOS\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mS\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"VCC\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mG\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mD\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"Vout\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mratio\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m9\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     21\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 22\u001b[0;31m \u001b[0mres\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msolve\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfull_output\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m~/.repo/spice.py/spice.py\u001b[0m in \u001b[0;36msolve\u001b[0;34m(gnd, max_delta, eps, N, disp, full_output)\u001b[0m\n\u001b[1;32m    196\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mdisp\u001b[0m\u001b[0;34m>\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0meqs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mEdge\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtotal\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    197\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mdisp\u001b[0m\u001b[0;34m>\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0meig\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0meqs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mEdge\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtotal\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 198\u001b[0;31m         \u001b[0msol\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m-\u001b[0m\u001b[0mlsolve\u001b[0m\u001b[0;34m(\u001b[0m \u001b[0meqs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mEdge\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtotal\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0meqs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mEdge\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtotal\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    199\u001b[0m         \u001b[0msol\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mconcat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msol\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0meye\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mMOSFET\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mall\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    200\u001b[0m         \u001b[0mdone\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<__array_function__ internals>\u001b[0m in \u001b[0;36msolve\u001b[0;34m(*args, **kwargs)\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/numpy/linalg/linalg.py\u001b[0m in \u001b[0;36msolve\u001b[0;34m(a, b)\u001b[0m\n\u001b[1;32m    391\u001b[0m     \u001b[0msignature\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'DD->D'\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misComplexType\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m'dd->d'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    392\u001b[0m     \u001b[0mextobj\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mget_linalg_error_extobj\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m_raise_linalgerror_singular\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 393\u001b[0;31m     \u001b[0mr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgufunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msignature\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mextobj\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mextobj\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    394\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    395\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0mwrap\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mastype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult_t\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcopy\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/numpy/linalg/linalg.py\u001b[0m in \u001b[0;36m_raise_linalgerror_singular\u001b[0;34m(err, flag)\u001b[0m\n\u001b[1;32m     86\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     87\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_raise_linalgerror_singular\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0merr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mflag\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 88\u001b[0;31m     \u001b[0;32mraise\u001b[0m \u001b[0mLinAlgError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Singular matrix\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     89\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     90\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_raise_linalgerror_nonposdef\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0merr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mflag\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mLinAlgError\u001b[0m: Singular matrix"
     ]
    }
   ],
   "source": [
    "V(\"VCC\",\"GND\",10)\n",
    "V1=V(\"V1\",\"GND\",5) #共模输入\n",
    "V2=V(\"V2\",\"V1\",4e-3) #差分输入\n",
    "\n",
    "# 上面的电流镜\n",
    "PMOS(D=2,G=2,S=\"VCC\",ratio=5/11)\n",
    "PMOS(D=3,G=2,S=\"VCC\",ratio=5/11)\n",
    "\n",
    "# 下面的电流镜\n",
    "R(\"VCC\",1,1e4)\n",
    "NMOS(D=1,     G=1,S=\"GND\",ratio= 1)\n",
    "NMOS(D=4,     G=1,S=\"GND\",ratio=.2)\n",
    "NMOS(D=\"Vout\",G=1,S=\"GND\",ratio= 1)\n",
    "\n",
    "# 输入MOS管\n",
    "NMOS(D=2,G=\"V1\",S=4,ratio=4)\n",
    "NMOS(D=3,G=\"V2\",S=4,ratio=4)\n",
    "\n",
    "# 输出MOS管\n",
    "PMOS(S=\"VCC\",G=3,D=\"Vout\",ratio=9/2)\n",
    "\n",
    "res = solve(full_output=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cc8c98f0",
   "metadata": {},
   "source": [
    "程序报错，提示有奇异矩阵。事实上，如果一个环路完全由MOS管源漏相连组成，就会出现以上错误。可通过手动添加几个小电阻解决。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "56dd49c4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "15999.99999184\n",
      "15991.640721142576\n",
      "15723.733415880179\n",
      "14935.133474720164\n",
      "13734.76035570073\n",
      "12368.010513035244\n",
      "10842.20444906071\n",
      "8872.424551419212\n",
      "6284.303041633575\n",
      "3539.1196670560716\n",
      "1547.0764849600018\n",
      "795.2586583210235\n",
      "360.65739827590886\n",
      "166.05656336092778\n",
      "2.1657965938941856e-05\n",
      "2.0256645199318198e-06\n",
      "2.7139994584004807e-08\n",
      "res(sol=array([-8.55460217e-04,  0.00000000e+00,  0.00000000e+00,  3.92059983e-04,\n",
      "        3.92059983e-04,  6.86506792e-05,  3.94749553e-04,  3.42513194e-05,\n",
      "        3.43993597e-05,  3.94749553e-04, -3.42513194e-05, -3.43993597e-05,\n",
      "        3.42513194e-05,  3.43993597e-05, -3.94749553e-04,  6.07940017e+00,\n",
      "        4.08423528e+00,  6.80711513e+00, -3.81017600e+00, -4.25886016e+00,\n",
      "        2.10558869e+00,  1.65690452e+00, -3.19288448e+00,  1.00000000e+00]), done=True, step=18, msg='')\n"
     ]
    }
   ],
   "source": [
    "clear() # 清楚之前的电路。重画电路必须调用\n",
    "\n",
    "V(\"VCC\",\"GND\",10)\n",
    "V1=V(\"V1\",\"GND\",5)\n",
    "V2=V(\"V2\",\"V1\",4e-3)\n",
    "\n",
    "R(\"VCC\",1,1e4)\n",
    "NMOS(D=1,     G=1,S=\"GND\",ratio= 1)\n",
    "NMOS(D=4,     G=1,S=\"GND\",ratio=.2)\n",
    "NMOS(D=\"Vout\",G=1,S=\"GND\",ratio= 1)\n",
    "\n",
    "R(\"VCC\",\"X1\",1e-3)\n",
    "R(\"VCC\",\"X2\",1e-3)\n",
    "R(\"VCC\",\"X3\",1e-3)\n",
    "\n",
    "PMOS(D=2,G=2,S=\"X1\",ratio=5/11)\n",
    "PMOS(D=3,G=2,S=\"X2\",ratio=5/11)\n",
    "\n",
    "NMOS(D=2,G=\"V1\",S=4,ratio=4)\n",
    "NMOS(D=3,G=\"V2\",S=4,ratio=4)\n",
    "\n",
    "PMOS(S=\"X3\",G=3,D=\"Vout\",ratio=9/2)\n",
    "\n",
    "res=solve(full_output=True,disp=1)\n",
    "print(res)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "da2c6cc4",
   "metadata": {},
   "source": [
    "以上结果显示了求解过程中Newton-Raphson迭代中误差的变化。\n",
    "\n",
    "接下来计算差分输入从-0.1V到0.1V变化时输出的变化。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "9c5a68b9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7f81911c2a60>]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "vdc = linspace(-.1,.1,200)\n",
    "vout = []\n",
    "for v in vdc:\n",
    "    V2.U = v\n",
    "    res = solve(eps=1e-8,N=1000,disp=0,full_output=True)\n",
    "    if not res.done:\n",
    "        print(res.msg)\n",
    "        break\n",
    "    vout.append(Vertex(\"Vout\").V @ res.sol)\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "plt.plot(vdc,vout)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
